// @Author miaoqing
// @Date 2024/02/23 10:27:00
// @Desc
package logic

import (
	"core/common"
	"core/component/function"
	"core/component/logger"
	"core/component/timer"
	"core/ini"
	"core/network"
	"fmt"
	"net"
	"runtime/debug"
	"strconv"
	"sync"
	"time"
)

var (
	server *Server
	once   sync.Once
)

const (
	httpService = "online-http"
)

type Server struct {
	network.Service
	id          string
	tcpServer   *network.TcpServer
	timer       *timer.Timer
	processIdx  int
	conf        *ini.Config
	httpAddr    string
	httpPort    int
	httpHandler *HTTPHandler
	startTime   int64
}

func ServerInstance() *Server {
	once.Do(func() {
		server = &Server{
			tcpServer:   &network.TcpServer{},
			httpHandler: newHttpHandler(),
			timer:       timer.NewTimer(),
		}
		server.Impl = server
	})
	return server
}

func (srv *Server) registerTimer() {
	srv.timer.RegTimer(gatewayClientMgrGetMe().checkConnect, 1*time.Second)
	srv.timer.RegTimer(gatewayClientMgrGetMe().discoveryGatewaySrv, 1.*time.Second)
	srv.timer.RegTimer(pvpClientMgrGetMe().checkConnect, 1*time.Second)
	srv.timer.RegTimer(pvpClientMgrGetMe().discoveryPvpSrv, 1.*time.Second)
	srv.timer.RegTimer(centerClientMgrGetMe().checkConnect, 1*time.Second)
	srv.timer.RegTimer(centerClientMgrGetMe().discoveryCenterSrv, 1*time.Second)
	srv.timer.RegTimer(srv.addHttpPort2Center, 1*time.Second)
	srv.timer.RegTimer(srv.startCenterMq, 1*time.Second)
}

func (srv *Server) Init(cfg interface{}, processIdx int) {
	c, ok := cfg.(*ini.Config)
	if !ok {
		return
	}
	srv.conf = c
	srv.processIdx = processIdx

	srv.startTime = time.Now().Unix()

	srv.httpPort = srv.conf.Server.OnlineHttpPort + processIdx
	srv.httpAddr = srv.conf.Server.OnlineHttpIp + ":" + strconv.Itoa(srv.httpPort)
	srv.id = strconv.FormatUint(function.IpAddressStringToUint64(srv.httpAddr), 10)
	srv.registerTimer()

	logger.Infof("OnlineID:%v pidx:%v", srv.id, processIdx)
}

func (srv *Server) Run() {
	startHTTPServer(srv.httpAddr, srv.httpHandler)

	go func() {
		tick := time.NewTicker(time.Second * 1)
		defer func() {
			tick.Stop()
			if err := recover(); err != nil {
				logger.Error("[异常] 全局定时器出错", err, "\n", string(debug.Stack()))
			}
		}()

		for {
			select {
			case <-tick.C:
				srv.timer.Loop()
			}
		}
	}()
}

func (srv *Server) Finialize() {
	req1 := &common.RemoveServerReq{ServerID: srv.id}
	_ = common.SendCenterHttpRequest(req1, nil, "POST", "/removeOnlineHttpPort")
	WorldGetMe().FinializeSave()
}

func (srv *Server) getNSQChannel() string {
	host, port, err := net.SplitHostPort(srv.httpAddr)
	if err != nil {
		return srv.id
	}
	return fmt.Sprintf("channel-%v-%v", host, port)
}

func (srv *Server) addHttpPort2Center() {
	req := &common.AddServerReq{
		SI: &common.ServerInfo{
			ServerID: srv.id,
			Port:     srv.httpPort,
		},
	}
	_ = common.SendCenterHttpRequest(req, nil, "POST", "/addOnlineHttPort")
}

func (srv *Server) startCenterMq() {
	centerMqStart(CommonTopic, srv.id)
}
